<?php

namespace VueRender;

use Closure;
use VueRender\Contracts\ComponentInterface;
use VueRender\Support\Js;
use VueRender\Traits\HasBase;

/**
 * @property string $componentName 组件名称
 * @property array $props 组件属性
 * @property Schema|array|string|boolean|int|null $children 子根组
 */
abstract class Schema extends Fluent implements ComponentInterface
{
    use HasBase;

    /**
     * @param mixed|null $children
     * @return $this
     */
    public function children(mixed $children = null): static
    {
        $child = $this->children?:[];
        if ($children!==null){
            if ($children instanceof Closure){
                $children($this);
            }elseif (is_array($children)){
                $this->children = array_merge($child,$children);
            }else{
                $child[] = $children;
                $this->children = $child;
            }
        }
        return $this;
    }

    /**
     * @param mixed|null $children
     * @return $this
     */
    public function addChildren(mixed $children = null): static
    {
        $this->children = $children;
        return $this;
    }

    /**
     * @return $this
     */
    public function render(): static
    {
        $name = $this->componentName;
        $options = $this->handleChildren($this->children);
        $attrs = $this->attrs?implode(" ",$this->attrs):"";
        if ($options){
            $children = "\n".$options."\n";
            $this->element = "<$name $attrs>$children</$name>";
        }else{
            $this->element = "<$name $attrs />";
        }
        return $this;
    }

    /**
     * @param $children
     * @return string
     */
    protected function handleChildren($children){
        $options = [];
        if (is_array($children)){
            foreach ($children as $child){
                $options[] = $this->handleChildren($child);
            }
        }elseif($children instanceof Schema){
            $options[] = $children->render()->getElement();
            $this->mergeRefs($children->getRefs());
            $this->mergeStates($children->getStates());
            $this->mergeMethods($children->getMethods());
        }elseif(is_bool($children)){
            $options[] = $children?'true':'false';
        }else{
            $options[] = $children;
        }
        return implode("",$options);
    }
}
